﻿using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace GISDeveloping_test4
{
    /// <summary>
    /// 用于进行属性查询的窗体
    /// </summary>
    public partial class FormExpQuery : Form
    {
        IMap map;
        ILayerFields m_layerfields;
        IFeatureLayer m_featurelayer;
        IHookHelper hookHelper;
        int selectedFieldType;
        IFeatureSelection m_featureSelection;

        public FormExpQuery(IHookHelper hookHelper)
        {
            InitializeComponent();
            this.hookHelper = hookHelper;
            map = hookHelper.FocusMap;
        }





        private void FormExpQuery_Load(object sender, EventArgs e)
        {
            cbxAddLayer();
        }




        /// <summary>
        /// 当LayerComboBox选项发生变化时，FieldComboBox显示所选图层的字段
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void LayerComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (GetLayers() == null)
            {
                return;
            }
            IEnumLayer layers = GetLayers();
            IField m_field;
            ILayer m_layer;
            int fieldType;
            layers.Reset();
            FieldComboBox.Items.Clear();
            ValueComboBox.Items.Clear();
            while ((m_layer = layers.Next()) != null)
            {
                if (m_layer.Name != LayerComboBox.Text)
                {
                    continue;
                }
                this.m_layerfields = m_layer as ILayerFields;
                for (int i = 0; i < m_layerfields.FieldCount; i++)
                {
                    m_field = m_layerfields.get_Field(i);
                    fieldType = (int)m_field.Type;
                    if (fieldType == 7)//esriFieldType=7表示esriFieldTypeGeometry
                    {
                        continue;//不显示shape字段
                    }
                    FieldComboBox.Items.Add(m_field.Name);
                }
            }
            m_featurelayer = GetFeatureLayer(LayerComboBox.Text);
            if (FieldComboBox.Items.Count > 0)//设置默认选择ObjectID
            {
                FieldComboBox.SelectedIndex = 0;
            }
        }


        /// <summary>
        /// 当FieldComboBox选择项变化时发生，获取所选图层所选
        /// 字段上的所有唯一值
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FieldComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            // 获取所选字段名
            string selectedFieldName = FieldComboBox.SelectedItem as string;
            ValueComboBox.Items.Clear();
            ValueComboBox.Text = "";

            // 获取所选图层
            IFeatureLayer selectedLayer = GetFeatureLayer(LayerComboBox.Text);

            if (selectedLayer != null)
            {
                // 获取字段索引
                int fieldIndex = selectedLayer.FeatureClass.FindField(selectedFieldName);

                //获取字段类型
                IField m_field = m_layerfields.get_Field(fieldIndex);
                selectedFieldType = (int)m_field.Type;

                // 使用游标获取唯一值
                IQueryFilter queryFilter = new QueryFilterClass();
                queryFilter.SubFields = selectedFieldName;
                ICursor cursor = (ICursor)selectedLayer.FeatureClass.Search(queryFilter, true);
                //创建数据统计对象，用于统计唯一值
                IDataStatistics dataStatistics = new DataStatisticsClass();
                dataStatistics.Field = selectedFieldName;
                dataStatistics.Cursor = cursor;

                // 获取唯一值集合，创建并遍历包含唯一值的枚举器
                System.Collections.IEnumerator enumerator = dataStatistics.UniqueValues;
                while (enumerator.MoveNext())
                {
                    object uniqueValue = enumerator.Current;
                    ValueComboBox.Items.Add(uniqueValue);
                }

                // 释放游标
                Marshal.ReleaseComObject(cursor);
            }
        }





        /// <summary>
        /// 获取map中的所有图层
        /// </summary>
        /// <returns></returns>
        private IEnumLayer GetLayers()
        {

            if (map.LayerCount == 0)
            {
                return null;
            }
            return map.Layers;
        }




        /// <summary>
        /// 向layerComboBox中添加图层名
        /// </summary>
        public void cbxAddLayer()
        {
            if (GetLayers() == null) return;
            IEnumLayer layers = GetLayers();
            layers.Reset();
            ILayer layer = null;
            while ((layer = layers.Next()) != null)
            {
                if (layer is IFeatureLayer)
                    LayerComboBox.Items.Add(layer.Name);
            }

            //设置第一个图层为默认选项
            if (LayerComboBox.Items.Count > 0)
            {
                LayerComboBox.SelectedIndex = 0;
            }
        }


        /// <summary>
        /// 根据图层名称返回FeatureLayer
        /// </summary>
        /// <param name="layername"></param>
        /// <returns></returns>
        public IFeatureLayer GetFeatureLayer(string layername)
        {
            if (GetLayers() == null)
                return null;
            IEnumLayer layers = GetLayers();
            layers.Reset();
            ILayer layer = null;
            while ((layer = layers.Next()) != null)
            {
                if (layer.Name == layername)
                    return layer as IFeatureLayer;
            }
            return null;
        }

        private void SearchAttButton_Click(object sender, EventArgs e)
        {
            // 获取用户选择的条件、字段和值
            string selectedPredicate = PredicateComboBox.SelectedItem as string;
            string selectedFieldName = FieldComboBox.SelectedItem as string;
            object selectedValue = ValueComboBox.SelectedItem;
            AxMapControl axMapControl = Control.FromHandle(new IntPtr(this.hookHelper.ActiveView.ScreenDisplay.hWnd)) as AxMapControl;

            for (int i = 0; i < map.LayerCount; i++)
            {
                ILayer layer = map.Layer[i];
                //判断是否选择了正确的图层
                if (layer.Name == LayerComboBox.SelectedItem.ToString())
                {
                    IFeatureLayer featureLayer = GetFeatureLayer(layer.Name);
                    IFeatureSelection featureSelection = featureLayer as IFeatureSelection;

                    IQueryFilter queryFilter = new QueryFilterClass();
                    //构造查询语句
                    if (selectedFieldType == 4)//表示字段类型为esriFieldTypeString
                    {
                        queryFilter.WhereClause = $"{selectedFieldName} {selectedPredicate} '{selectedValue}'";
                    }
                    else
                    {
                        queryFilter.WhereClause = $"{selectedFieldName} {selectedPredicate} {selectedValue}";
                    }
                    //构造游标
                    IFeatureCursor cursor = featureLayer.Search(queryFilter, true);
                    IFeature feature = cursor.NextFeature();

                    while (feature != null)
                    {
                        featureSelection.SelectFeatures(queryFilter, esriSelectionResultEnum.esriSelectionResultAdd, false);
                        feature = cursor.NextFeature();
                    }
                    m_featureSelection = featureSelection;
                    hookHelper.ActiveView.Refresh();//高亮显示被选中的要素
                    FlashFeatures(map);
                }
            }
        }



        /// <summary>
        /// 闪烁地图选择集中的要素
        /// </summary>
        /// <param name="map"></param>
        private void FlashFeatures(IMap map)
        {

            IHookActions hookActions = hookHelper as IHookActions;
            //获取FeatureSelection
            ISelection selection = map.FeatureSelection;
            //从FeatureSelection获取enumFeature
            IEnumFeature enumFeature = selection as IEnumFeature;
            enumFeature.Reset();

            //循环Features，将其中的Feature添加到Array
            IFeature feature = enumFeature.Next();
            IArray array = new ESRI.ArcGIS.esriSystem.Array();
            while (feature != null)
            {
                array.Add(feature.Shape);
                feature = enumFeature.Next();
            }

            ILayer layer = map.get_Layer(GetLayerIndexByName(map, LayerComboBox.SelectedItem.ToString()));
            //利用HookActions使array中的元素闪烁
            if (hookActions.get_ActionSupportedOnMultiple(array, esriHookActions.esriHookActionsFlash))
            {
                if (layer.Visible == true)
                {
                    hookActions.DoActionOnMultiple(array, esriHookActions.esriHookActionsFlash);
                }

            }

        }



        private int GetLayerIndexByName(IMap map, string name)
        {
            int layerIndex = -1;

            // 遍历地图中的图层集合
            for (int i = 0; i < map.LayerCount; i++)
            {
                ILayer layer = map.get_Layer(i);

                // 检查图层名是否与目标图层名相符
                if (layer.Name == name)
                {
                    // 找到目标图层，记录索引并跳出循环
                    layerIndex = i;
                    break;
                }

            }
            return layerIndex;

        }

        private void CenterDisplayButton_Click(object sender, EventArgs e)
        {
            //从hookhelper获取AxMapControl
            AxMapControl axMapControl = Control.FromHandle(new IntPtr(this.hookHelper.ActiveView.ScreenDisplay.hWnd)) as AxMapControl;
            ZoomToSelectedFeatures(map, axMapControl);
        }



        /// <summary>
        /// 缩放到选中的要素
        /// </summary>
        /// <param name="featureSelection"></param>
        /// <param name="axMapControl"></param>
        private void ZoomToSelectedFeatures(IMap map, AxMapControl axMapControl)
        {
            //从map中获取选择集
            ISelection selection = map.FeatureSelection;
            IEnumFeature enumFeature = selection as IEnumFeature;
            IEnvelope envelope = new EnvelopeClass();

            enumFeature.Reset();
            IFeature selectedFeature = enumFeature.Next();

            //循环选择集中的要素，将其区域的范围进行合并
            while (selectedFeature != null)
            {
                envelope.Union(selectedFeature.Shape.Envelope);
                selectedFeature = enumFeature.Next();
            }
            if (!envelope.IsEmpty)
            {
                // Expand为可选操作，扩大envelope为选定区域的1.2倍大小
                envelope.Expand(1.2, 1.2, true);
                axMapControl.Extent = envelope;
                axMapControl.Refresh();
            }
        }

    }
}

